import {
    Component,
    Host,
    h,
    Element,
    Prop,
    ComponentInterface,
    State,
    Watch,
    Event,
    EventEmitter,
} from '@stencil/core';
import interact from 'interactjs';

/**
 * 分割面板
 *
 * @export
 * @class IBzSplitPanel
 * @implements {ComponentInterface}
 */
@Component({
    tag: 'ibz-split-panel',
    styleUrl: 'ibz-split-panel.scss',
    shadow: true,
})
export class IBzSplitPanel implements ComponentInterface {
    /**
     * 当前组件
     *
     * @type {HTMLIbzSplitPanelElement}
     * @memberof IBzSplitPanel
     */
    @Element()
    el: HTMLIbzSplitPanelElement;

    /**
     * 分割线DOM实例
     *
     * @type {HTMLDivElement}
     * @memberof IBzSplitPanel
     */
    line: HTMLDivElement;

    /**
     * horizontal: 左右分割，vertical: 上下分割
     *
     * @type {('horizontal' | 'vertical')}
     * @memberof IBzSplitPanel
     */
    @Prop()
    mode: 'horizontal' | 'vertical' = 'horizontal';

    /**
     * 保险数值
     *
     * @memberof IBzSplitPanel
     */
    @Prop()
    insuranceNum = 50;

    /**
     * 分割比例，小于1按照比例算。大于等于1按照px算
     *
     * @memberof IBzSplitPanel
     */
    @Prop()
    split = 0.3;
    @Watch('split')
    splitWatch(): void {
        this.calcDefaultNum();
    }

    /**
     * 分割值变更事件
     *
     * @type {EventEmitter<number>}
     * @memberof IBzSplitPanel
     */
    @Event({ eventName: 'split-change' })
    splitChange: EventEmitter<number>;

    /**
     * 分割宽度参数
     *
     * @memberof IBzSplitPanel
     */
    @State()
    num = 100;

    /**
     * 是否为上下布局
     *
     * @memberof IBzSplitPanel
     */
    isVertical = false;

    /**
     * 鼠标显示符号
     *
     * @memberof IBzSplitPanel
     */
    mouseCursor = 'col-resize';

    /**
     * 计算默认宽或高
     *
     * @memberof IBzSplitPanel
     */
    calcDefaultNum(): void {
        if (isNaN(this.split)) {
            this.split = 0.3;
        }
        if (this.split >= 1) {
            if (this.isVertical) {
                this.num = this.el.offsetHeight - this.split;
            } else {
                this.num = this.split;
            }
        } else {
            if (this.isVertical) {
                this.num = this.el.offsetHeight - this.el.offsetHeight * this.split;
            } else {
                this.num = this.el.offsetWidth * this.split;
            }
        }
    }

    componentDidLoad() {
        // 计算方向
        this.isVertical = this.mode === 'vertical';
        this.calcDefaultNum();
        // 计算展示值
        this.mouseCursor = !this.isVertical ? 'col-resize' : 'row-resize';
        const axis = !this.isVertical ? 'x' : 'y';
        interact(this.line).draggable({
            // 锁定起始轴
            startAxis: axis,
            // 锁定可拖拽轴
            lockAxis: axis,
            // 设置拖拽生效区域
            modifiers: [
                // 保持在父对象内部
                interact.modifiers.restrictEdges({ outer: this.el }),
            ],
            cursorChecker: () => {
                return this.mouseCursor;
            },
            onmove: (e: any) => {
                this.splitMove(e);
            },
        });
    }

    splitMove(e: any) {
        if (this.isVertical) {
            const newNum = this.num + e.delta.y;
            if (newNum < this.insuranceNum) {
                return;
            }
            if (newNum > this.el.offsetHeight - this.insuranceNum) {
                return;
            }
            this.num = newNum;
        } else {
            const newNum = this.num + e.delta.x;
            if (newNum < this.insuranceNum) {
                return;
            }
            if (newNum > this.el.offsetWidth - this.insuranceNum) {
                return;
            }
            this.num = newNum;
        }
        this.splitChange.emit(this.num);
    }

    render() {
        const style: any = {};
        const lineStyle: any = {};
        if (this.isVertical) {
            style.height = this.num + 'px';
            lineStyle.top = style.height;
        } else {
            style.width = this.num + 'px';
            lineStyle.left = style.width;
        }
        return (
            <Host>
                <div
                    class={{ 'ibz-split-panel-wrapper': true, horizontal: !this.isVertical, vertical: this.isVertical }}
                >
                    <div
                        class={{
                            'ibz-split-panel': true,
                            left: !this.isVertical,
                            top: this.isVertical,
                        }}
                        style={style}
                    >
                        <slot />
                    </div>
                    <div ref={ref => (this.line = ref)} class='dividing-line' style={lineStyle} />
                    <div
                        class={{
                            'ibz-split-panel': true,
                            right: !this.isVertical,
                            bottom: this.isVertical,
                        }}
                    >
                        <slot name='content' />
                    </div>
                </div>
            </Host>
        );
    }
}
